home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / uucp-104.lha / uucp-1.04 / protf.c < prev    next >
C/C++ Source or Header  |  1993-02-13  |  20KB  |  843 lines

  1. /* protf.c
  2.    The 'f' protocol.
  3.  
  4.    Copyright (C) 1991, 1992 Ian Lance Taylor
  5.  
  6.    This file is part of the Taylor UUCP package.
  7.  
  8.    This program is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU General Public License as
  10.    published by the Free Software Foundation; either version 2 of the
  11.    License, or (at your option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
  24.    */
  25.  
  26. #include "uucp.h"
  27.  
  28. #if USE_RCS_ID
  29. const char protf_rcsid[] = "$Id: protf.c,v 1.28 1993/01/19 05:10:46 ian Rel $";
  30. #endif
  31.  
  32. #include <ctype.h>
  33. #include <errno.h>
  34.  
  35. #include "uudefs.h"
  36. #include "uuconf.h"
  37. #include "conn.h"
  38. #include "trans.h"
  39. #include "system.h"
  40. #include "prot.h"
  41.  
  42. /* This implementation is based on code by Piet Beertema, CWI,
  43.    Amsterdam, Sep 1984.
  44.  
  45.    This code implements the 'f' protocol, which requires a
  46.    flow-controlled error-free seven-bit data path.  It does check for
  47.    errors, but only at the end of each file transmission, so a noisy
  48.    line without error correcting modems will be unusable.
  49.  
  50.    The conversion to seven bit data is done as follows, where b
  51.    represents the character to convert:
  52.  
  53.       0 <= b <=  037: 0172, b + 0100 (0100 to 0137)
  54.     040 <= b <= 0171:       b        ( 040 to 0171)
  55.    0172 <= b <= 0177: 0173, b - 0100 ( 072 to 077)
  56.    0200 <= b <= 0237: 0174, b - 0100 (0100 to 0137)
  57.    0240 <= b <= 0371: 0175, b - 0200 ( 040 to 0171)
  58.    0372 <= b <= 0377: 0176, b - 0300 ( 072 to 077)
  59.  
  60.    This causes all output bytes to be in the range 040 to 0176; these
  61.    are the printable ASCII characters.  */
  62.  
  63. /* This structure is used to hold information when dealing with the
  64.    end of file acknowledgement.  */
  65.  
  66. struct sfinfo
  67. {
  68.   /* The functions from the generic code.  */
  69.   boolean (*psendfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon));
  70.   boolean (*precfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon,
  71.                const char *zdata, size_t cdata));
  72.   /* The info pointer from the generic code.  */
  73.   pointer pinfo;
  74.   /* The character to send after receiving the checksum.  */
  75.   char bsend;
  76. };
  77.  
  78. /* Internal functions.  */
  79. static boolean ffprocess_data P((struct sdaemon *qdaemon,
  80.                  boolean *pfexit, size_t *pcneed));
  81. static boolean ffawait_ack P((struct stransfer *qtrans,
  82.                   struct sdaemon *qdaemon,
  83.                   const char *zdata, size_t cdata));
  84. static boolean ffawait_cksum P((struct stransfer *qtrans,
  85.                 struct sdaemon *qdaemon,
  86.                 const char *zdata, size_t cdata));
  87. static boolean ffsend_ack P((struct stransfer *qtrans,
  88.                  struct sdaemon *qdaemon));
  89.  
  90. /* The size of the buffer we allocate to store outgoing data in.  */
  91. #define CFBUFSIZE (256)
  92.  
  93. /* The timeout to wait for data to arrive before giving up.  */
  94. static int cFtimeout = 120;
  95.  
  96. /* The maximum number of retries.  */
  97. static int cFmaxretries = 2;
  98.  
  99. /* The buffer we allocate for outgoing data.  */
  100. static char *zFbuf;
  101.  
  102. /* TRUE if we are receiving a file rather than a command.  */
  103. static boolean fFfile;
  104.  
  105. /* The checksum so far.  */
  106. static unsigned int iFcheck;
  107.  
  108. /* The last special byte (0172 to 0176) or 0 if none.  */
  109. static char bFspecial;
  110.  
  111. /* The number of times we have retried this file.  */
  112. static int cFretries;
  113.  
  114. /* Whether this file has been acknowledged.  */
  115. static boolean fFacked;
  116.  
  117. struct uuconf_cmdtab asFproto_params[] =
  118. {
  119.   { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cFtimeout, NULL },
  120.   { "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cFmaxretries, NULL },
  121.   { NULL, 0, NULL, NULL }
  122. };
  123.  
  124. /* Statistics.  */
  125.  
  126. /* The number of data bytes sent in files.  */
  127. static long cFsent_data;
  128.  
  129. /* The number of actual bytes sent in files.  */
  130. static long cFsent_bytes;
  131.  
  132. /* The number of data bytes received in files.  */
  133. static long cFrec_data;
  134.  
  135. /* The number of actual bytes received in files.  */
  136. static long cFrec_bytes;
  137.  
  138. /* The number of file retries when sending.  */
  139. static long cFsend_retries;
  140.  
  141. /* The number of file retries when receiving.  */
  142. static long cFrec_retries;
  143.  
  144. /* Start the protocol.  */
  145.  
  146. boolean
  147. ffstart (qdaemon, pzlog)
  148.      struct sdaemon *qdaemon;
  149.      char **pzlog;
  150. {
  151.   *pzlog = NULL;
  152.  
  153.   cFsent_data = 0;
  154.   cFsent_bytes = 0;
  155.   cFrec_data = 0;
  156.   cFrec_bytes = 0;
  157.   cFsend_retries = 0;
  158.   cFrec_retries = 0;
  159.  
  160.   /* Use XON/XOFF handshaking.  */
  161.   if (! fconn_set (qdaemon->qconn, PARITYSETTING_DEFAULT,
  162.            STRIPSETTING_SEVENBITS, XONXOFF_ON))
  163.     return FALSE;
  164.  
  165.   /* We sleep to allow the other side to reset the terminal; this is
  166.      what Mr. Beertema's code does.  */
  167.   usysdep_sleep (2);
  168.  
  169.   return TRUE;
  170. }
  171.  
  172. /* Shutdown the protocol.  */
  173.  
  174. /*ARGSIGNORED*/
  175. boolean
  176. ffshutdown (qdaemon)
  177.      struct sdaemon *qdaemon;
  178. {
  179.   xfree ((pointer) zFbuf);
  180.   zFbuf = NULL;
  181.   ulog (LOG_NORMAL,
  182.     "Protocol 'f': sent %ld bytes for %ld, received %ld bytes for %ld",
  183.     cFsent_bytes, cFsent_data, cFrec_bytes, cFrec_data);
  184.   if (cFsend_retries != 0 || cFrec_retries != 0)
  185.     ulog (LOG_NORMAL, "Protocol 'f' file retries: %ld sending, %ld receiving",
  186.       cFsend_retries, cFrec_retries);
  187.   cFtimeout = 120;
  188.   cFmaxretries = 2;
  189.   return TRUE;
  190. }
  191.  
  192. /* Send a command string.  We just send the string followed by a carriage
  193.    return.  */
  194.  
  195. /*ARGSUSED*/
  196. boolean
  197. ffsendcmd (qdaemon, z, ilocal, iremote)
  198.      struct sdaemon *qdaemon;
  199.      const char *z;
  200.      int ilocal;
  201.      int iremote;
  202. {
  203.   size_t clen;
  204.   char *zalc;
  205.   boolean fret;
  206.  
  207.   DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "ffsendcmd: Sending command \"%s\"", z);
  208.  
  209.   clen = strlen (z);
  210.   zalc = zbufalc (clen + 2);
  211.   memcpy (zalc, z, clen);
  212.   zalc[clen] = '\r';
  213.   zalc[clen + 1] = '\0';
  214.   fret = fsend_data (qdaemon->qconn, zalc, clen + 1, TRUE);
  215.   ubuffree (zalc);
  216.   return fret;
  217. }
  218.  
  219. /* Get space to be filled with data.  We allocate the space from the
  220.    heap.  */
  221.  
  222. /*ARGSIGNORED*/
  223. char *
  224. zfgetspace (qdaemon, pclen)
  225.      struct sdaemon *qdaemon;
  226.      size_t *pclen;
  227. {
  228.   *pclen = CFBUFSIZE;
  229.   if (zFbuf == NULL)
  230.     zFbuf = (char *) xmalloc (CFBUFSIZE);
  231.   return zFbuf;
  232. }
  233.  
  234. /* Send out a data packet.  We have to encode the data into seven bits
  235.    and accumulate a checksum.  */
  236.  
  237. /*ARGSIGNORED*/
  238. boolean
  239. ffsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
  240.      struct sdaemon *qdaemon;
  241.      char *zdata;
  242.      size_t cdata;
  243.      int ilocal;
  244.      int iremote;
  245.      long ipos;
  246. {
  247.   char ab[CFBUFSIZE * 2];
  248.   char *ze;
  249.   register unsigned int itmpchk;
  250.       
  251.   cFsent_data += cdata;
  252.  
  253.   ze = ab;
  254.   itmpchk = iFcheck;
  255.   while (cdata-- > 0)
  256.     {
  257.       register int b;
  258.  
  259.       /* Rotate the checksum left.  */
  260.       if ((itmpchk & 0x8000) == 0)
  261.     itmpchk <<= 1;
  262.       else
  263.     {
  264.       itmpchk <<= 1;
  265.       ++itmpchk;
  266.     }
  267.  
  268.       /* Add the next byte into the checksum.  */
  269.       b = *zdata++ & 0xff;
  270.       itmpchk += b;
  271.  
  272.       /* Encode the byte.  */
  273.       if (b <= 0177)
  274.     {
  275.       if (b <= 037)
  276.         {
  277.           *ze++ = '\172';
  278.           *ze++ = (char) (b + 0100);
  279.         }
  280.       else if (b <= 0171)
  281.         *ze++ = (char) b;
  282.       else
  283.         {
  284.           *ze++ = '\173';
  285.           *ze++ = (char) (b - 0100);
  286.         }
  287.     }
  288.       else
  289.     {
  290.       if (b <= 0237)
  291.         {
  292.           *ze++ = '\174';
  293.           *ze++ = (char) (b - 0100);
  294.         }
  295.       else if (b <= 0371)
  296.         {
  297.           *ze++ = '\175';
  298.           *ze++ = (char) (b - 0200);
  299.         }
  300.       else
  301.         {
  302.           *ze++ = '\176';
  303.           *ze++ = (char) (b - 0300);
  304.         }
  305.     }
  306.     }
  307.  
  308.   iFcheck = itmpchk;
  309.  
  310.   cFsent_bytes += ze - ab;
  311.  
  312.   /* Passing FALSE tells fsend_data not to bother looking for incoming
  313.      information, since we really don't expect any.  */
  314.   return fsend_data (qdaemon->qconn, ab, (size_t) (ze - ab), FALSE);
  315. }
  316.  
  317. /* Process data and return the amount of data we are looking for in
  318.    *pcneed.  The 'f' protocol doesn't really reveal this, but when
  319.    transferring file we know that we need at least seven characters
  320.    for the checksum.  */
  321.  
  322. static boolean
  323. ffprocess_data (qdaemon, pfexit, pcneed)
  324.      struct sdaemon *qdaemon;
  325.      boolean *pfexit;
  326.      size_t *pcneed;
  327. {
  328.   int i;
  329.   register unsigned int itmpchk;
  330.  
  331.   *pfexit = FALSE;
  332.   if (pcneed != NULL)
  333.     *pcneed = 1;
  334.  
  335.   if (! fFfile)
  336.     {
  337.       /* A command continues until a '\r' character, which we turn
  338.      into '\0' before calling fgot_data.  */
  339.       while (iPrecstart != iPrecend)
  340.     {
  341.       for (i = iPrecstart; i < CRECBUFLEN && i != iPrecend; i++)
  342.         {
  343.           if (abPrecbuf[i] == '\r')
  344.         {
  345.           int istart;
  346.  
  347.           DEBUG_MESSAGE1 (DEBUG_PROTO,
  348.                   "ffprocess_data: Got %d command bytes",
  349.                   i - iPrecstart + 1);
  350.  
  351.           abPrecbuf[i] = '\0';
  352.           istart = iPrecstart;
  353.           iPrecstart = (i + 1) % CRECBUFLEN;
  354.           if (pcneed != NULL)
  355.             *pcneed = 0;
  356.           return fgot_data (qdaemon, abPrecbuf + istart,
  357.                     (size_t) (i - istart + 1),
  358.                     (const char *) NULL, (size_t) 0,
  359.                     -1, -1, (long) -1, TRUE, pfexit);
  360.         }
  361.         }
  362.  
  363.       DEBUG_MESSAGE1 (DEBUG_PROTO,
  364.               "ffprocess_data: Got %d command bytes",
  365.               i - iPrecstart);
  366.  
  367.       if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
  368.                (size_t) (i - iPrecstart),
  369.                (const char *) NULL, (size_t) 0,
  370.                -1, -1, (long) -1, TRUE, pfexit))
  371.         return FALSE;
  372.  
  373.       iPrecstart = i % CRECBUFLEN;
  374.     }
  375.  
  376.       return TRUE;
  377.     }
  378.  
  379.   /* Here the data is destined for a file, and we must decode it.  */
  380.  
  381.   itmpchk = iFcheck;
  382.  
  383.   while (iPrecstart != iPrecend)
  384.     {
  385.       char *zstart, *zto, *zfrom;
  386.       int c;
  387.  
  388.       zto = zfrom = zstart = abPrecbuf + iPrecstart;
  389.  
  390.       c = iPrecend - iPrecstart;
  391.       if (c < 0)
  392.     c = CRECBUFLEN - iPrecstart;
  393.  
  394.       while (c-- != 0)
  395.     {
  396.       int b;
  397.  
  398.       b = *zfrom++ & 0xff;
  399.       if (b < 040 || b > 0176)
  400.         {
  401.           ulog (LOG_ERROR, "Illegal byte %d", b);
  402.           continue;
  403.         }
  404.  
  405.       /* Characters >= 0172 are always special characters.  The
  406.          only legal pair of consecutive special characters
  407.          are 0176 0176 which immediately precede the four
  408.          digit checksum.  */
  409.       if (b >= 0172)
  410.         {
  411.           if (bFspecial != 0)
  412.         {
  413.           if (bFspecial != 0176 || b != 0176)
  414.             {
  415.               ulog (LOG_ERROR, "Illegal bytes %d %d",
  416.                 bFspecial, b);
  417.               bFspecial = 0;
  418.               continue;
  419.             }
  420.  
  421.           /* Pass any initial data.  */
  422.           if (zto != zstart)
  423.             {
  424.               /* Don't count the checksum in the received bytes.  */
  425.               cFrec_bytes += zfrom - zstart - 2;
  426.               cFrec_data += zto - zstart;
  427.               if (! fgot_data (qdaemon, zstart,
  428.                        (size_t) (zto - zstart),
  429.                        (const char *) NULL, (size_t) 0,
  430.                        -1, -1, (long) -1, TRUE, pfexit))
  431.             return FALSE;
  432.             }
  433.  
  434.           /* The next characters we want to read are the
  435.              checksum, so skip the second 0176.  */
  436.           iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
  437.  
  438.           iFcheck = itmpchk;
  439.  
  440.           /* Tell fgot_data that we've read the entire file by
  441.              passing 0 length data.  This will wind up calling
  442.              fffile to verify the checksum.  We set *pcneed to
  443.              0 because we don't want to read any more data
  444.              from the port, since we may have already read the
  445.              checksum.  */
  446.           if (pcneed != NULL)
  447.             *pcneed = 0;
  448.           return fgot_data (qdaemon, (const char *) NULL,
  449.                     (size_t) 0, (const char *) NULL,
  450.                     (size_t) 0, -1, -1, (long) -1,
  451.                     TRUE, pfexit);
  452.         }
  453.  
  454.           /* Here we have encountered a special character that
  455.          does not follow another special character.  */
  456.           bFspecial = (char) b;
  457.         }
  458.       else
  459.         {
  460.           int bnext;
  461.  
  462.           /* Here we have encountered a nonspecial character.  */
  463.  
  464.           switch (bFspecial)
  465.         {
  466.         default:
  467.           bnext = b;
  468.           break;
  469.         case 0172:
  470.           bnext = b - 0100;
  471.           break;
  472.         case 0173:
  473.         case 0174:
  474.           bnext = b + 0100;
  475.           break;
  476.         case 0175:
  477.           bnext = b + 0200;
  478.           break;
  479.         case 0176:
  480.           bnext = b + 0300;
  481.           break;
  482.         }
  483.  
  484.           *zto++ = (char) bnext;
  485.           bFspecial = 0;
  486.  
  487.           /* Rotate the checksum left.  */
  488.           if ((itmpchk & 0x8000) == 0)
  489.         itmpchk <<= 1;
  490.           else
  491.         {
  492.           itmpchk <<= 1;
  493.           ++itmpchk;
  494.         }
  495.  
  496.           /* Add the next byte into the checksum.  */
  497.           itmpchk += bnext;
  498.         }
  499.     }
  500.  
  501.       if (zto != zstart)
  502.     {
  503.       DEBUG_MESSAGE1 (DEBUG_PROTO,
  504.               "ffprocess_data: Got %d bytes",
  505.               zto - zstart);
  506.  
  507.       cFrec_data += zto - zstart;
  508.       if (! fgot_data (qdaemon, zstart, (size_t) (zto - zstart),
  509.                (const char *) NULL, (size_t) 0,
  510.                -1, -1, (long) -1, TRUE, pfexit))
  511.         return FALSE;
  512.     }
  513.  
  514.       cFrec_bytes += zfrom - zstart;
  515.  
  516.       iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
  517.     }
  518.  
  519.   iFcheck = itmpchk;
  520.  
  521.   if (pcneed != NULL)
  522.     {
  523.       /* At this point we may have seen the first 0176 in the checksum
  524.      but not the second.  The checksum is at least seven
  525.      characters long (0176 0176 a b c d \r).  This won't help
  526.      much, but reading seven characters is a lot better than
  527.      reading two, which is what I saw in a 2400 baud log file.  */
  528.       if (bFspecial == 0176)
  529.     *pcneed = 6;
  530.       else
  531.     *pcneed = 7;
  532.     }
  533.  
  534.   return TRUE;
  535. }
  536.  
  537. /* Wait for data to come in and process it until we've finished a
  538.    command or a file.  */
  539.  
  540. boolean
  541. ffwait (qdaemon)
  542.      struct sdaemon *qdaemon;
  543. {
  544.   while (TRUE)
  545.     {
  546.       boolean fexit;
  547.       size_t cneed, crec;
  548.  
  549.       if (! ffprocess_data (qdaemon, &fexit, &cneed))
  550.     return FALSE;
  551.       if (fexit)
  552.     return TRUE;
  553.  
  554.       if (cneed > 0)
  555.     {
  556.       /* We really want to do something like get all available
  557.          characters, then sleep for half a second and get all
  558.          available characters again, and keep this up until we
  559.          don't get anything after sleeping.  */
  560.       if (! freceive_data (qdaemon->qconn, cneed, &crec, cFtimeout, TRUE))
  561.         return FALSE;
  562.       if (crec == 0)
  563.         {
  564.           ulog (LOG_ERROR, "Timed out waiting for data");
  565.           return FALSE;
  566.         }
  567.     }
  568.     }
  569. }
  570.  
  571. /* File level operations.  Reset the checksums when starting to send
  572.    or receive a file, and output the checksum when we've finished
  573.    sending a file.  */
  574.  
  575. /*ARGSUSED*/
  576. boolean
  577. fffile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
  578.      struct sdaemon *qdaemon;
  579.      struct stransfer *qtrans;
  580.      boolean fstart;
  581.      boolean fsend;
  582.      long cbytes;
  583.      boolean *pfhandled;
  584. {
  585.   DEBUG_MESSAGE3 (DEBUG_PROTO, "fffile: fstart %s; fsend %s; fFacked %s",
  586.           fstart ? "true" : "false", fsend ? "true" : "false",
  587.           fFacked ? "true" : "false");
  588.  
  589.   *pfhandled = FALSE;
  590.  
  591.   if (fstart)
  592.     {
  593.       iFcheck = 0xffff;
  594.       cFretries = 0;
  595.       fFacked = FALSE;
  596.       if (! fsend)
  597.     {
  598.       bFspecial = 0;
  599.       fFfile = TRUE;
  600.     }
  601.       return TRUE;
  602.     }
  603.   else
  604.     {
  605.       struct sfinfo *qinfo;
  606.  
  607.       /* We need to handle the checksum and the acknowledgement.  If
  608.      we get a successful ACK, we set fFacked to TRUE and call the
  609.      send or receive function by hand.  This will wind up calling
  610.      here again, so if fFacked is TRUE we just return out and let
  611.      the send or receive function do whatever it does.  This is a
  612.      bit of a hack.  */
  613.       if (fFacked)
  614.     {
  615.       fFacked = FALSE;
  616.       return TRUE;
  617.     }
  618.  
  619.       if (fsend)
  620.     {
  621.       char ab[sizeof "\176\176ABCD\r"];
  622.  
  623.       /* Send the final checksum.  */
  624.       sprintf (ab, "\176\176%04x\r", iFcheck & 0xffff);
  625.       if (! fsend_data (qdaemon->qconn, ab, (size_t) 7, TRUE))
  626.         return FALSE;
  627.  
  628.       /* Now wait for the acknowledgement.  */
  629.       fFfile = FALSE;
  630.       qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
  631.       qinfo->psendfn = qtrans->psendfn;
  632.       qinfo->precfn = qtrans->precfn;
  633.       qinfo->pinfo = qtrans->pinfo;
  634.       qtrans->psendfn = NULL;
  635.       qtrans->precfn = ffawait_ack;
  636.       qtrans->pinfo = (pointer) qinfo;
  637.       qtrans->fcmd = TRUE;
  638.  
  639.       *pfhandled = TRUE;
  640.  
  641.       return fqueue_receive (qdaemon, qtrans);
  642.     }
  643.       else
  644.     {
  645.       /* Wait for the checksum.  */
  646.       fFfile = FALSE;
  647.       qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
  648.       qinfo->psendfn = qtrans->psendfn;
  649.       qinfo->precfn = qtrans->precfn;
  650.       qinfo->pinfo = qtrans->pinfo;
  651.       qtrans->psendfn = NULL;
  652.       qtrans->precfn = ffawait_cksum;
  653.       qtrans->pinfo = (pointer) qinfo;
  654.       qtrans->fcmd = TRUE;
  655.  
  656.       *pfhandled = TRUE;
  657.  
  658.       return fqueue_receive (qdaemon, qtrans);
  659.     }
  660.     }
  661. }
  662.  
  663. /* Wait for the ack after sending a file and the checksum.  */
  664.  
  665. static boolean
  666. ffawait_ack (qtrans, qdaemon, zdata, cdata)
  667.      struct stransfer *qtrans;
  668.      struct sdaemon *qdaemon;
  669.      const char *zdata;
  670.      size_t cdata;
  671. {
  672.   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
  673.  
  674.   qtrans->precfn = NULL;
  675.  
  676.   /* An R means to retry sending the file.  */
  677.   if (*zdata == 'R')
  678.     {
  679.       if (! ffileisopen (qtrans->e))
  680.     {
  681.       ulog (LOG_ERROR, "Request to resent non-file");
  682.       return FALSE;
  683.     }
  684.  
  685.       ++cFretries;
  686.       if (cFretries > cFmaxretries)
  687.     {
  688.       ulog (LOG_ERROR, "Too many retries");
  689.       return FALSE;
  690.     }
  691.  
  692.       ulog (LOG_NORMAL, "Resending file");
  693.       if (! ffilerewind (qtrans->e))
  694.     {
  695.       ulog (LOG_ERROR, "rewind: %s", strerror (errno));
  696.       return FALSE;
  697.     }
  698.       qtrans->ipos = (long) 0;
  699.  
  700.       iFcheck = 0xffff;
  701.       ++cFsend_retries;
  702.  
  703.       qtrans->psendfn = qinfo->psendfn;
  704.       qtrans->precfn = qinfo->precfn;
  705.       qtrans->pinfo = qinfo->pinfo;
  706.       xfree ((pointer) qinfo);
  707.       qtrans->fsendfile = TRUE;
  708.  
  709.       return fqueue_send (qdaemon, qtrans);
  710.     }
  711.  
  712.   if (*zdata != 'G')
  713.     {
  714.       DEBUG_MESSAGE1 (DEBUG_PROTO, "fffile: Got \"%s\"", zdata);
  715.       ulog (LOG_ERROR, "File send failed");
  716.       return FALSE;
  717.     }
  718.  
  719.   qtrans->psendfn = qinfo->psendfn;
  720.   qtrans->precfn = qinfo->precfn;
  721.   qtrans->pinfo = qinfo->pinfo;
  722.   xfree ((pointer) qinfo);
  723.  
  724.   /* Now call the send function by hand after setting fFacked to TRUE.
  725.      Since fFacked is true fffile will simply return out, and the send
  726.      function can do whatever it what was going to do.  */
  727.   fFacked = TRUE;
  728.   return (*qtrans->psendfn) (qtrans, qdaemon);
  729. }
  730.  
  731. /* This function is called when the checksum arrives.  */
  732.  
  733. /*ARGSUSED*/
  734. static boolean
  735. ffawait_cksum (qtrans, qdaemon, zdata, cdata)
  736.      struct stransfer *qtrans;
  737.      struct sdaemon *qdaemon;
  738.      const char *zdata;
  739.      size_t cdata;
  740. {
  741.   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
  742.   unsigned int icheck;
  743.  
  744.   qtrans->precfn = NULL;
  745.  
  746.   if (! isxdigit (zdata[0])
  747.       || ! isxdigit (zdata[1])
  748.       || ! isxdigit (zdata[2])
  749.       || ! isxdigit (zdata[3])
  750.       || zdata[4] != '\0')
  751.     {
  752.       ulog (LOG_ERROR, "Bad checksum format");
  753.       xfree (qtrans->pinfo);
  754.       return FALSE;
  755.     }
  756.       
  757.   icheck = (unsigned int) strtol ((char *) zdata, (char **) NULL, 16);
  758.  
  759.   if (icheck != (iFcheck & 0xffff))
  760.     {
  761.       DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
  762.               "Checksum failed; calculated 0x%x, got 0x%x",
  763.               iFcheck & 0xffff, icheck);
  764.  
  765.       if (! ffileisopen (qtrans->e))
  766.     {
  767.       ulog (LOG_ERROR, "Failed to get non-file");
  768.       return FALSE;
  769.     }
  770.  
  771.       ++cFretries;
  772.       if (cFretries > cFmaxretries)
  773.     {
  774.       ulog (LOG_ERROR, "Too many retries");
  775.       qinfo->bsend = 'Q';
  776.     }
  777.       else
  778.     {
  779.       ulog (LOG_NORMAL, "File being resent");
  780.  
  781.       /* This bit of code relies on the receive code setting
  782.          qtrans->s.ztemp to the full name of the temporary file
  783.          being used.  */
  784.       qtrans->e = esysdep_truncate (qtrans->e, qtrans->s.ztemp);
  785.       if (! ffileisopen (qtrans->e))
  786.         return FALSE;
  787.       qtrans->ipos = (long) 0;
  788.  
  789.       iFcheck = 0xffff;
  790.       bFspecial = 0;
  791.       fFfile = TRUE;
  792.       ++cFrec_retries;
  793.  
  794.       /* Send an R to tell the other side to resend the file.  */
  795.       qinfo->bsend = 'R';
  796.     }
  797.     }
  798.   else
  799.     {
  800.       /* Send a G to tell the other side the file was received
  801.      correctly.  */
  802.       qinfo->bsend = 'G';
  803.     }
  804.  
  805.   qtrans->psendfn = ffsend_ack;
  806.  
  807.   return fqueue_send (qdaemon, qtrans);
  808. }
  809.  
  810. /* Send the acknowledgement, and then possible wait for the resent
  811.    file.  */
  812.  
  813. static boolean
  814. ffsend_ack (qtrans, qdaemon)
  815.      struct stransfer *qtrans;
  816.      struct sdaemon *qdaemon;
  817. {
  818.   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
  819.   char ab[2];
  820.  
  821.   ab[0] = qinfo->bsend;
  822.   ab[1] = '\0';
  823.   if (! ffsendcmd (qdaemon, ab, 0, 0))
  824.     return FALSE;
  825.  
  826.   qtrans->psendfn = qinfo->psendfn;
  827.   qtrans->precfn = qinfo->precfn;
  828.   qtrans->pinfo = qinfo->pinfo;
  829.   xfree ((pointer) qinfo);
  830.  
  831.   if (ab[0] == 'Q')
  832.     return FALSE;
  833.   if (ab[0] == 'R')
  834.     {
  835.       qtrans->frecfile = TRUE;
  836.       return fqueue_receive (qdaemon, qtrans);
  837.     }
  838.  
  839.   fFacked = TRUE;
  840.   return (*qtrans->precfn) (qtrans, qdaemon, (const char *) NULL,
  841.                 (size_t) 0);
  842. }
  843.